package com.ease.integration.service.impl;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.ease.common.util.Assertion;
import com.ease.common.util.Detect;
import com.ease.integration.context.vo.IntegrationServiceContext;
import com.ease.integration.context.vo.IntegrationServiceDispatchWrapperContext;
import com.ease.integration.converter.ArgumentObjectInterconverter;
import com.ease.integration.converter.IntegrationValueConverterFactory;
import com.ease.integration.definition.constant.IntegrationMessageTemplateReserveKey;
import com.ease.integration.definition.service.IntegrationServiceDefinitionManagementService;
import com.ease.integration.definition.vo.IntegrationServiceDefinition;
import com.ease.integration.message.ResponseMessage;
import com.ease.integration.service.ExternalServiceDispatcher;
import com.ease.integration.service.ExternalServiceDispatcherWrapper;

/**
 * ExternalServiceDispatcherWrapperImpl完成传输对象的封装
 * 
 * ExternalServiceDispatcherImpl是接口实现,放在本地或远程都可以,调用cxf的接口就在本地,调用axis的就在远程
 * 
 * @author nathanleewei
 * 
 */
public class ExternalServiceDispatcherWrapperImpl implements ExternalServiceDispatcherWrapper {

	private static final transient Log log = LogFactory.getLog(ExternalServiceDispatcherWrapperImpl.class);

	private IntegrationServiceDefinitionManagementService integrationServiceDefinitionManagementService;

	private IntegrationValueConverterFactory integrationValueConverterFactory;

	private ExternalServiceDispatcher externalServiceDispatcher;

	public IntegrationServiceContext doService(IntegrationServiceContext integrationServiceContext) {
		/* 根据RMI传输对象的信息得到请求的context */
		String integrationServiceDefinitionKey = integrationServiceContext.getIntegrationServiceDefinitionKey();
		IntegrationServiceDefinition integrationServiceDefinition = integrationServiceDefinitionManagementService.getIntegrationServiceDefinitionByKey(integrationServiceDefinitionKey);
		Assertion.notNull(integrationServiceDefinition, "请求" + integrationServiceDefinitionKey + "找不到定义上下文");

		/* 根据context把请求对象转为出参 */

		// 对象转为多个出参的办法,模板内容用分隔符分隔出每个参数,然后按分隔符把每段顺序设入object[]
		Map<String, Object> map = new HashMap<String, Object>();
		map.put(IntegrationMessageTemplateReserveKey.INTEGRATION_VALUEOBJECT, integrationServiceContext.getRequestMessage());
		map.putAll(integrationValueConverterFactory.getConverters());

		Map<String, Object> requestMap = ArgumentObjectInterconverter
				.objectToParameters(map, integrationServiceDefinition.getRequestMessageDefinition().getMessageArgumentRepresentationTemplatePath());

		if (log.isDebugEnabled()) {
			StringBuffer sb = new StringBuffer();
			sb.append("接口输出信息:\r\nintegrationServiceDefinitionKey: " + integrationServiceDefinitionKey + "\r\n");
			for (Map.Entry<String, Object> entry : requestMap.entrySet()) {
				sb.append("arg[" + entry.getKey() + "]: " + entry.getValue() + "\r\n");
			}
			log.debug(sb.toString());
		}

		IntegrationServiceDispatchWrapperContext integrationServiceDispatchWrapperContext = new IntegrationServiceDispatchWrapperContext(integrationServiceDefinition.getKey(),
				integrationServiceDefinition.getExternalServiceName(), requestMap);

		try {
			Map<String, Object> responseArguments = externalServiceDispatcher.doService(integrationServiceDefinition.getKey(), integrationServiceDefinition.getIntegrationServiceBeanMethodName(),
					integrationServiceContext.getServiceKey(), integrationServiceDefinition.getExternalServiceName(), requestMap);
			integrationServiceDispatchWrapperContext.setResponseArguments(responseArguments);
		} catch (Exception e) {
			log.error(e, e);
		}

		if (log.isDebugEnabled()) {
			StringBuffer sb = new StringBuffer();
			sb.append("接口返回信息:\r\nintegrationServiceDefinitionKey: " + integrationServiceDefinitionKey + "\r\n");
			if (Detect.notEmpty(integrationServiceDispatchWrapperContext.getResponseArguments())) {
				for (Map.Entry<String, Object> entry : integrationServiceDispatchWrapperContext.getResponseArguments().entrySet()) {
					sb.append("arg[" + entry.getKey() + "]: " + entry.getValue() + "\r\n");
				}
			} else {
				sb.append("接口返回信息为空:\r\nintegrationServiceDefinitionKey: " + integrationServiceDefinitionKey + "\r\n");
			}
			log.debug(sb.toString());
		}
		// 根据template将入参转为内部xml,同时用转换器做值映射
		Map<String, Object> rootMap = new HashMap<String, Object>();
		if (Detect.notEmpty(integrationServiceDispatchWrapperContext.getResponseArguments())) {
			rootMap.putAll(integrationServiceDispatchWrapperContext.getResponseArguments());
		}

		List<String> xmlStyleArgumentKeys = ArgumentObjectInterconverter.getKeysOfXmlStyleRequestArgument(integrationServiceDefinition.getResponseMessageDefinition()
				.getMessageArgumentRepresentationTemplatePath());
		if (Detect.notEmpty(xmlStyleArgumentKeys)) {
			for (String key : xmlStyleArgumentKeys) {
				String xmlPart = (String) integrationServiceDispatchWrapperContext.getResponseArguments().get(key);
				if (Detect.notEmpty(xmlPart)) {
					rootMap.put(IntegrationMessageTemplateReserveKey.XML_STRING + key, xmlPart);
				}
			}
		}
		rootMap.putAll(integrationValueConverterFactory.getConverters());

		// 根据command取得vo
		// 将内部xml转为vo
		ResponseMessage responseMessage = (ResponseMessage) ArgumentObjectInterconverter.parameterToObject(rootMap, integrationServiceDefinition.getResponseMessageDefinition()
				.getMessageXmlRepresentationTemplatePath(), integrationServiceDefinition.getResponseMessageDefinition().getMessageClass());

		integrationServiceContext.setResponseMessage(responseMessage);

		return integrationServiceContext;
	}

	public IntegrationValueConverterFactory getIntegrationValueConverterFactory() {
		return integrationValueConverterFactory;
	}

	public void setIntegrationValueConverterFactory(IntegrationValueConverterFactory integrationValueConverterFactory) {
		this.integrationValueConverterFactory = integrationValueConverterFactory;
	}

	public IntegrationServiceDefinitionManagementService getIntegrationServiceDefinitionManagementService() {
		return integrationServiceDefinitionManagementService;
	}

	public void setIntegrationServiceDefinitionManagementService(IntegrationServiceDefinitionManagementService integrationServiceDefinitionManagementService) {
		this.integrationServiceDefinitionManagementService = integrationServiceDefinitionManagementService;
	}

	public ExternalServiceDispatcher getExternalServiceDispatcher() {
		return externalServiceDispatcher;
	}

	public void setExternalServiceDispatcher(ExternalServiceDispatcher externalServiceDispatcher) {
		this.externalServiceDispatcher = externalServiceDispatcher;
	}

}
